﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using DynORM.ValueObjects;
using DynORM.Enums;
using DynORM.ReferenceObjects;
using DynORM.Mappers;
using DynORM.Interfaces;

namespace UnitTests.DAL
{
    [TestClass]
    public class PostgreSQLSelectWithPredicate
    {
        static string dbName = "TestDB";
        static string pooling = "Pooling=false;";//otherwise it won't let drop db (db will be in use with connections in pool)
        static string connectionStringToDatabase = "Server=127.0.0.1;Port=5432;User Id=postgres;Password=postgres;Database=" + dbName + ";" + pooling;
        static string connectionStringToServer = "Server=127.0.0.1;Port=5432;User Id=postgres;Password=postgres;" + pooling;

        [TestInitialize]
        public void TestInit()
        {
            DatabaseMapper.CreateDatabase(connectionStringToServer, DBMSTypes.PostgreSQL, new Database(dbName));
        }

        [TestCleanup]
        public void TestClean()
        {
            DatabaseMapper.DropDatabase(connectionStringToServer, DBMSTypes.PostgreSQL, dbName);
        }

        void CreateNewRowDescriptor(string tableName, DBMSTypes dbmsTypes)
        {
            Dictionary<int, IFieldDescriptor> pkFieldDescs = new Dictionary<int, IFieldDescriptor>();
            pkFieldDescs.Add(0, new FieldDescriptor(typeof(Guid), "RowID"));
            PrimaryKeyDescriptor pkd = new PrimaryKeyDescriptor(tableName, pkFieldDescs, tableName + "_PK");
            List<FieldDescriptor> fieldDescs = new List<FieldDescriptor>();
            fieldDescs.Add(new FieldDescriptor(typeof(string), "Name"));
            RowDescriptor rd = new RowDescriptor(tableName, fieldDescs, new List<IRelationDescriptor>() { pkd });
            RowDescriptorMapper.Store(connectionStringToDatabase, dbmsTypes, rd);
        }

        void DropRowDescriptor(string tableName, DBMSTypes dbmsTypes)
        {
            RowDescriptorMapper.Drop(connectionStringToDatabase, dbmsTypes, tableName);
        }

        void AddRow(string tableName, DBMSTypes dbmsTypes, Guid id, string name)
        {
            IRowDescriptor rd = RowDescriptorMapper.Retrieve(connectionStringToDatabase, dbmsTypes, tableName);
            Assert.AreEqual(tableName, rd.RelationDescriptors.First<IRelationDescriptor>(r => r.RelationType == RelationType.PrimaryKey).TableName);
            Row row = new Row(rd, id, name);
            //row["TestColumn"] = "some test entity name";
            RowMapper.RowWrite(connectionStringToDatabase, dbmsTypes, row);
        }


        [TestMethod]
        public void SelectByName()
        {
            string tableName = "TestTableForSelect";
            DBMSTypes dbmsTypes = DBMSTypes.PostgreSQL;
            CreateNewRowDescriptor(tableName, dbmsTypes);
            AddRow(tableName, dbmsTypes, Guid.NewGuid(), "Name01");
            AddRow(tableName, dbmsTypes, Guid.NewGuid(), "Name02");
            AddRow(tableName, dbmsTypes, Guid.NewGuid(), "Name03");
            AddRow(tableName, dbmsTypes, Guid.NewGuid(), "Name04");
            AddRow(tableName, dbmsTypes, Guid.NewGuid(), "Name05");
            List<IORMComparison> predicate = new List<IORMComparison>();
            IORMComparison condition = new Comparison("Name", ORMComparisonOperator.Equal, "Name03");
            predicate.Add(condition);
            IEnumerable<IRow> rows = RowMapper.RowsRead(connectionStringToDatabase, dbmsTypes, tableName, predicate);
            Assert.AreEqual<int>(1, rows.Count());
            IRow row = rows.First<IRow>();
            Assert.AreEqual("Name03", row["Name"]);
            DropRowDescriptor(tableName, dbmsTypes);
        }

        [TestMethod]
        public void SelectByNameNotEqual()
        {
            string tableName = "TestTableForSelect";
            DBMSTypes dbmsTypes = DBMSTypes.PostgreSQL;
            CreateNewRowDescriptor(tableName, dbmsTypes);
            AddRow(tableName, dbmsTypes, Guid.NewGuid(), "Name01");
            AddRow(tableName, dbmsTypes, Guid.NewGuid(), "Name02");
            AddRow(tableName, dbmsTypes, Guid.NewGuid(), "Name03");
            AddRow(tableName, dbmsTypes, Guid.NewGuid(), "Name04");
            AddRow(tableName, dbmsTypes, Guid.NewGuid(), "Name05");
            List<IORMComparison> predicate = new List<IORMComparison>();
            IORMComparison condition = new Comparison("Name", ORMComparisonOperator.NotEqual, "Name03");
            predicate.Add(condition);
            IEnumerable<IRow> rows = RowMapper.RowsRead(connectionStringToDatabase, dbmsTypes, tableName, predicate);
            Assert.AreEqual<int>(4, rows.Count());
            DropRowDescriptor(tableName, dbmsTypes);
        }

    }
}
